package oa.hleast.xswl.service.article.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import oa.hleast.common.constant.CacheConstant;
import oa.hleast.common.constant.ConfigKeyConstant;
import oa.hleast.common.constant.DictCodeConstant;
import oa.hleast.common.web.exception.BizException;
import oa.hleast.xswl.common.config.AppProps;
import oa.hleast.xswl.common.constant.CommonConstant;
import oa.hleast.xswl.common.constant.LinkTypeEnum;
import oa.hleast.xswl.common.constant.ReviewStatusEnum;
import oa.hleast.xswl.mapper.article.InformationCentreMapper;
import oa.hleast.xswl.pojo.domain.SysCommonConfig;
import oa.hleast.xswl.pojo.domain.SysDictItem;
import oa.hleast.xswl.pojo.domain.article.CmsArticle;
import oa.hleast.xswl.pojo.form.article.CmsArticleForm;
import oa.hleast.xswl.pojo.vo.DictItemValueByUserVO;
import oa.hleast.xswl.pojo.vo.article.CmsArticleVo;
import oa.hleast.xswl.pojo.vo.article.ShowArticleVo;
import oa.hleast.xswl.service.ISysCommonConfigService;
import oa.hleast.xswl.service.ISysDictItemService;
import oa.hleast.xswl.service.article.IInformationCentreService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 302
 * @description
 * @date 2021/3/11
 */

@Transactional
@Slf4j
@Service
@AllArgsConstructor
public class InformationCentreServiceImpl extends ServiceImpl<InformationCentreMapper, CmsArticle> implements IInformationCentreService {

    //    private final UserFeignService userFeignService;
//    private final MemberFeignService memberFeignService;
    private final ISysCommonConfigService commonConfigService;
    private final ISysDictItemService dictItemService;
    private final InformationCentreMapper informationCentreMapper;
    private final AppProps appProps;


    /**
     * ===========  高级功能 ==========
     */

    @Override
    public List<CmsArticle> search(Integer page, Integer limit, String searchKey) {
        LambdaQueryWrapper<CmsArticle> queryWrapper = new LambdaQueryWrapper<CmsArticle>()
                .eq(CmsArticle::getReviewStatus, ReviewStatusEnum.PASS.getCode())
                // 不在去区分来源，都展示
//                .eq(CmsArticle::getAid, "")
                .like(CmsArticle::getKeyword, searchKey)
                .orderByDesc(CmsArticle::getGmtModified)
                .orderByDesc(CmsArticle::getGmtCreate);


        Page<CmsArticle> cmsArticlePage = this.page(new Page<>(page, limit), queryWrapper);
        return cmsArticlePage.getRecords();
    }

    @Override
    public CmsArticleVo getDetailByConfigKey(String configKey, Long userId) {
        SysCommonConfig configResult = commonConfigService.getByConfigKey(configKey);
        Long id = new Long(configResult.getValue());
        return this.getCacheDetail(id, userId);
    }

    @Override
    public List<CmsArticleVo> findDetailByConfigKey(List<String> configKeyList, Long userId) {
        if (CollectionUtils.isEmpty(configKeyList)) {
            log.info("没有 key 参数");
            return new ArrayList<>();
        }
        log.info("configKeyList = {}", configKeyList);
        List<CmsArticleVo> voList = configKeyList.stream().map(key -> {
            return getDetailByConfigKey(key, userId);
        }).collect(Collectors.toList());
        log.info("voList = {}", voList);
        return voList;
    }

    @Override
    public List<SysDictItem> findInformationType() {

        List<SysDictItem> dictItemResult = dictItemService.getByDictByCode(DictCodeConstant.INFORMATION_TYPE);
        if (ObjectUtils.isEmpty(dictItemResult) || ObjectUtils.isEmpty(dictItemResult.get(0))) {
            throw new BizException("获取资讯类型异常，请联系管理员");
        }


        List<SysDictItem> dataTemp = dictItemResult;
        log.info("dataTemp = {}", dataTemp);

        Long finalIntroductionArticleId = getIntroductionArticleId();
        List<SysDictItem> data = dataTemp.stream().filter(dictItem -> !dictItem.getId().equals(finalIntroductionArticleId)).collect(Collectors.toList());


        Collections.reverse(data);

        log.info("data => {}", data);
        return data;
    }

    @Override
    public List<DictItemValueByUserVO> findInformationTypeByUser(Long userId, boolean showAll) {
        return informationCentreMapper.findInformationTypeByUser(DictCodeConstant.INFORMATION_TYPE, userId, showAll);
    }

    @Override
    public CmsArticleVo getCacheDetail(Long id, Long userId) {
        // TODO 后面加缓存

        CmsArticle article = this.getById(id);
        CmsArticleVo cmsArticleVo = conversionToVo(article);

        //是否收藏
        boolean isFavorites = false;

        cmsArticleVo.setFavorites(isFavorites);
        log.info("cmsArticleVo => {}", cmsArticleVo);

        return cmsArticleVo;
    }

    @Override
    public Integer countById(Long id) {

        QueryWrapper<CmsArticle> condition = new QueryWrapper<CmsArticle>()
                .eq("id", id).last("limit 1");
        Integer count = informationCentreMapper.selectCount(condition);

        log.info("id = {} ,count = {}", id, count);
        return count;
    }

    public Page<ShowArticleVo> findPageRecommendList(Integer page, Integer limit) {

        LambdaQueryWrapper<CmsArticle> queryWrapper = new LambdaQueryWrapper<CmsArticle>()
                .eq(CmsArticle::getReviewStatus, ReviewStatusEnum.PASS.getCode())
                // 不在去区分来源，都展示
//                .eq(CmsArticle::getAid, "")
                .orderByDesc(CmsArticle::getGmtModified)
                .orderByDesc(CmsArticle::getGmtCreate);


        Page<CmsArticle> cmsArticlePage = this.page(new Page<>(page, limit), queryWrapper);

        Page<ShowArticleVo> showArticleVoPage = new Page<>(page, limit, cmsArticlePage.getTotal());

        List<ShowArticleVo> cmsArticleList = cmsArticlePage.getRecords().stream().map(this::conversionToShowVo).collect(Collectors.toList());
        showArticleVoPage.setRecords(cmsArticleList);

        log.info("从数据库获取咨询推荐数据,page = {},limit = {},showArticleVoPage = {}", page, limit, showArticleVoPage);
        return showArticleVoPage;
    }

    @Override
    public Page<ShowArticleVo> findPageHotRecommendList(Integer page, Integer limit) {
        log.info("page = {},limit = {}", page, limit);
        LambdaQueryWrapper<CmsArticle> queryWrapper = new LambdaQueryWrapper<CmsArticle>()
                .eq(CmsArticle::getReviewStatus, ReviewStatusEnum.PASS.getCode())
                // 不在去区分来源，都展示
//                .isNotNull(CmsArticle::getAid)
                .eq(CmsArticle::getLinkType, 0)
                .orderByDesc(CmsArticle::getGmtModified)
                .orderByDesc(CmsArticle::getGmtCreate);


        Page<CmsArticle> cmsArticlePage = this.page(new Page<>(page, limit), queryWrapper);

        Page<ShowArticleVo> showArticleVoPage = new Page<>(page, limit, cmsArticlePage.getTotal());

        List<ShowArticleVo> cmsArticleList = cmsArticlePage.getRecords().stream().map(this::conversionToShowVo).collect(Collectors.toList());
        showArticleVoPage.setRecords(cmsArticleList);

        log.info("从数据库获取咨询一码通热门推荐数据,page = {},limit = {},showArticleVoPage = {}", page, limit, showArticleVoPage);
        return showArticleVoPage;
    }


    @Override
    public Page<ShowArticleVo> findPageShowList(Integer page, Integer limit, String dictItemInformationId) {

        LambdaQueryWrapper<CmsArticle> queryWrapper = new LambdaQueryWrapper<CmsArticle>()
                .eq(CmsArticle::getReviewStatus, ReviewStatusEnum.PASS.getCode())
                // 不在去区分来源，都展示
//                .eq(CmsArticle::getAid, "")
                .orderByDesc(CmsArticle::getGmtModified)
                .orderByDesc(CmsArticle::getGmtCreate);

        //按各条件查找
        if (StringUtils.isNotBlank(dictItemInformationId)) {
            queryWrapper.eq(CmsArticle::getDictItemInformationId, dictItemInformationId);
        }

        Page<CmsArticle> cmsArticlePage = this.page(new Page<>(page, limit), queryWrapper);

        Page<ShowArticleVo> showArticleVoPage = new Page<>(page, limit);

        List<ShowArticleVo> cmsArticleList = cmsArticlePage.getRecords().stream().map(this::conversionToShowVo)
                .collect(Collectors.toList());
        showArticleVoPage.setRecords(cmsArticleList);
        showArticleVoPage.setTotal(cmsArticleList.size());

        log.info("从数据库获取咨询展示数据,page = {},limit = {},showArticleVoPage = {}", page, limit, showArticleVoPage);
        return showArticleVoPage;
    }


    /**
     * ==========  基础功能 CRUD ==========
     */

    @Override
    @CacheEvict(value = CacheConstant.INFORMATION_LIST_KEY, allEntries = true)
    public boolean add(CmsArticleForm articleFrom) {

        log.info("dicItemInformationId = {}", articleFrom.getDictItemInformationId());


        //检验资讯类型
        Long dictItemId = articleFrom.getDictItemInformationId();
        log.info("dictItemId => {} ", dictItemId);
        SysDictItem sysDictItem = dictItemService.getDictItemById(dictItemId);
        if (ObjectUtils.isEmpty(sysDictItem)) {
            throw new BizException("资讯类型错误！");
        }

        CmsArticle article = conversionToPojo(articleFrom);

        if (ObjectUtils.isEmpty(article)) {
            throw new BizException("参数错误");
        }
        article.setDictItemInformationId(sysDictItem.getId());


        boolean save = this.save(article);

        if (save && article.getLinkType() == LinkTypeEnum.LOCAL.getCode()) {
            article.setUrl(CommonConstant.INFORMATION_URL + article.getId());
            this.updateById(article);

            /*
            Result<SysCommonConfigVo> hostResult = userFeignService.getByConfigKey(ConfigKeyConstant.HOST_KEY);
            if (ObjectUtils.isNotEmpty(hostResult) && ObjectUtils.isNotEmpty(hostResult.getData())) {
                article.setUrl(hostResult.getData().getValue() + CommonConstant.INFORMATION_URL + article.getId());
                this.updateById(article);
            } else {
                log.info("没有找到 host_key 的值");
            }
             */
        }

        return save;
    }

    @Override
    public Page<CmsArticleVo> pageList(Integer page, Integer limit, String title, Integer reviewStatus, String dictItemInformationId) {

        LambdaQueryWrapper<CmsArticle> queryWrapper = new LambdaQueryWrapper<CmsArticle>()
                .orderByDesc(CmsArticle::getGmtModified)
                .orderByDesc(CmsArticle::getGmtCreate);

        //按各条件查找
        if (StringUtils.isNotBlank(dictItemInformationId)) {
            queryWrapper.eq(CmsArticle::getDictItemInformationId, dictItemInformationId);
        }
        if (ObjectUtils.isNotEmpty(reviewStatus) && reviewStatus != 0) {
            queryWrapper.eq(CmsArticle::getReviewStatus, reviewStatus);
        }

        if (StringUtils.isNotBlank(title)) {
            queryWrapper.like(CmsArticle::getTitle, title);
        }

        Page<CmsArticle> cmsArticlePage = this.page(new Page<>(page, limit), queryWrapper);

        if (cmsArticlePage.getTotal() == 0) {
            return new Page<>(page, limit);
        }

        List<CmsArticleVo> cmsArticleList = cmsArticlePage.getRecords().stream().map(this::conversionToVo).collect(Collectors.toList());

        Page<CmsArticleVo> cmsArticleVoPage = new Page<>(page, limit, cmsArticlePage.getTotal());
        cmsArticleVoPage.setRecords(cmsArticleList);

        return cmsArticleVoPage;
    }

    @Override
    @Caching(evict = {
            @CacheEvict(value = CacheConstant.INFORMATION_LIST_KEY, allEntries = true),
            @CacheEvict(value = CacheConstant.HOME_PAGE_RECOMMEND_INFORMATION, key = "#articleForm.id")
    })
    public boolean update(CmsArticleForm articleForm) {

        //校验ID
        CmsArticle cmsArticleOld = this.getById(articleForm.getId());
        if (ObjectUtils.isEmpty(cmsArticleOld)) {
            throw new BizException("没有找到该数据！");
        }

        log.info("cmsArticleOld = {}", cmsArticleOld.toString());


        if (ObjectUtils.isEmpty(cmsArticleOld.getDictItemInformationId())) {
            throw new BizException("该条数据没有资讯类型，禁止修改，请联系管理员");
        }

        //资讯类型不可更改
        if (!cmsArticleOld.getDictItemInformationId().equals(articleForm.getDictItemInformationId())) {
            throw new BizException("禁止修改资讯类型");
        }

        CmsArticle article = conversionToPojo(articleForm);
        if (ObjectUtils.isEmpty(article)) {
            throw new BizException("没有找到该数据！");
        }

        article.setId(cmsArticleOld.getId());

        // 如果旧数据 或者 更新数据为 本地链接类型 生成 本地链接
        if (article.getLinkType() == LinkTypeEnum.LOCAL.getCode()) {
            article.setUrl(CommonConstant.INFORMATION_URL + article.getId());
        }

        //编辑完后状态更改为未审核
        article.setReviewStatus(1);

        return this.updateById(article);
    }

    @Override
    @Caching(evict = {
            @CacheEvict(value = CacheConstant.INFORMATION_LIST_KEY, allEntries = true),
            @CacheEvict(value = CacheConstant.HOME_PAGE_RECOMMEND_INFORMATION, allEntries = true)
    })
    public boolean deleteByIds(List<String> asList) {
        if (CollectionUtils.isFull(asList)) {
            throw new BizException("没有选择任何数据，请重新操作！");
        }

        return this.removeByIds(asList);
    }

    @Override
    @CacheEvict(value = CacheConstant.INFORMATION_LIST_KEY, allEntries = true)
    public boolean review(Long id, Integer reviewStatus, String reason) {
        //校验id
        CmsArticle cmsArticle = this.getById(id);
        if (ObjectUtils.isEmpty(cmsArticle)) {
            throw new BizException("没有此数据！");
        }

        //校验审核状态
        ReviewStatusEnum reviewStatusEnum = ReviewStatusEnum.getValue(reviewStatus);
        if (ObjectUtils.isEmpty(reviewStatusEnum)) {
            throw new BizException("审核状态参数错误");
        }

        //TODO 审核通过后禁止驳回

        cmsArticle.setId(id);
        cmsArticle.setReviewStatus(reviewStatus);
        cmsArticle.setReason(reason);
        return this.updateById(cmsArticle);
    }

    @Override
    public CmsArticleVo detail(Long id) {

        CmsArticle cmsArticle = this.getById(id);

        return conversionToVo(cmsArticle);
    }


    private CmsArticle conversionToPojo(CmsArticleForm cmsArticleForm) {
        if (ObjectUtils.isEmpty(cmsArticleForm)) {
            return null;
        }

        CmsArticle article = new CmsArticle();
        BeanUtil.copyProperties(cmsArticleForm, article);

        return article;
    }

    private CmsArticleVo conversionToVo(CmsArticle cmsArticle) {
        if (ObjectUtils.isEmpty(cmsArticle)) {
            return new CmsArticleVo();
        }

        CmsArticleVo cmsArticleVo = new CmsArticleVo();
        BeanUtil.copyProperties(cmsArticle, cmsArticleVo);
        cmsArticleVo.setGmtCreateDate(cmsArticle.getGmtCreate());

        //资讯类型中文名
        SysDictItem itemValueResult = dictItemService.getDictItemById(cmsArticle.getDictItemInformationId());
        if (ObjectUtils.isNotEmpty(itemValueResult)) {
            SysDictItem sysDictItem = itemValueResult;
            cmsArticleVo.setInformationTypeNameCN(sysDictItem.getName());
            cmsArticleVo.setInformationTypeName(sysDictItem.getValue());
        }

        //审核状态名称
        ReviewStatusEnum statusEnum = ReviewStatusEnum.getValue(cmsArticle.getReviewStatus());
        if (ObjectUtils.isEmpty(statusEnum)) {
            cmsArticleVo.setReviewStatus(ReviewStatusEnum.UN_KNOWN.getCode());
            cmsArticleVo.setReviewStatusName(ReviewStatusEnum.UN_KNOWN.getName());
        } else {
            cmsArticleVo.setReviewStatus(statusEnum.getCode());
            cmsArticleVo.setReviewStatusName(statusEnum.getName());
        }

        // url 拼接
        if (cmsArticle.getLinkType() == 1) {
            cmsArticleVo.setUrl(getHots() + cmsArticle.getUrl());
        }

        return cmsArticleVo;
    }

    private ShowArticleVo conversionToShowVo(CmsArticle cmsArticle) {
        if (ObjectUtils.isEmpty(cmsArticle)) {
            return new ShowArticleVo();
        }

        ShowArticleVo showArticleVo = new ShowArticleVo();
        BeanUtil.copyProperties(cmsArticle, showArticleVo);


        //资讯类型中文名
        SysDictItem itemValueResult = dictItemService.getDictItemById(cmsArticle.getDictItemInformationId());
        if (ObjectUtils.isNotEmpty(itemValueResult)) {
            SysDictItem sysDictItem = itemValueResult;
            showArticleVo.setInformationTypeNameCN(sysDictItem.getName());
            showArticleVo.setInformationTypeName(sysDictItem.getValue());
        }

        //审核状态名称
        ReviewStatusEnum statusEnum = ReviewStatusEnum.getValue(cmsArticle.getReviewStatus());
        if (ObjectUtils.isEmpty(statusEnum)) {
            showArticleVo.setReviewStatus(ReviewStatusEnum.UN_KNOWN.getCode());
            showArticleVo.setReviewStatusName(ReviewStatusEnum.UN_KNOWN.getName());
        } else {
            showArticleVo.setReviewStatus(statusEnum.getCode());
            showArticleVo.setReviewStatusName(statusEnum.getName());
        }

        //添加时间
        showArticleVo.setGmtCreateDate(cmsArticle.getGmtCreate());

        // url 拼接
        if (cmsArticle.getLinkType() == 1) {
            showArticleVo.setUrl(getHots() + cmsArticle.getUrl());
        }

        return showArticleVo;
    }

    private String getHots() {
        String htmlHost = appProps.getHtmlHost();
        log.info("htmlHost = {}", htmlHost);
        return htmlHost;
    }

    /**
     * 获取内部文章的类型ID
     */
    private Long getIntroductionArticleId() {
        Long introductionArticleId = 0L;
        try {
            String value = commonConfigService.getByConfigKey(ConfigKeyConstant.INTRODUCTION_ARTICLE_ITEM_ID).getValue();
            introductionArticleId = new Long(value);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("e = {}", e, e);
        }

        return introductionArticleId;
    }

}
